#include "kwdb_client.h"
#include "exceptions.h"

#include <thread>
#include <future>
#include <stdexcept>

namespace kwdb {

KWDBClient::KWDBClient(const ClientConfig& config)
    : config_(config)
    , grpcClient_(std::make_unique<GrpcClient>(config_))
    , batchWriter_(std::make_unique<BatchWriter>(config_, *grpcClient_))
    , parser_(std::make_unique<LineProtocolParser>())
    , connected_(false)
    , shutdown_(false) {
}

KWDBClient::~KWDBClient() {
    disconnect();
}

void KWDBClient::connect() {
    try {
        grpcClient_->connect();
        batchWriter_->start();
        initializeThreadPool();
        connected_ = true;
    } catch (const std::exception& e) {
        throw ConnectionException("连接失败: " + std::string(e.what()));
    }
}

void KWDBClient::disconnect() {
    if (connected_) {
        shutdown_ = true;
        batchWriter_->stop();
        shutdownThreadPool();
        grpcClient_->disconnect();
        connected_ = false;
    }
}

void KWDBClient::write(const DataPoint& dataPoint) {
    if (!connected_) {
        throw WriteException("客户端未连接");
    }
    
    try {
        batchWriter_->addDataPoint(dataPoint);
    } catch (const std::exception& e) {
        throw WriteException("写入失败: " + std::string(e.what()));
    }
}

std::future<void> KWDBClient::writeAsync(const DataPoint& dataPoint) {
    return std::async(std::launch::async, [this, dataPoint]() {
        write(dataPoint);
    });
}

void KWDBClient::writeBatch(const std::vector<DataPoint>& dataPoints) {
    if (!connected_) {
        throw WriteException("客户端未连接");
    }
    
    try {
        grpcClient_->writeBatch(dataPoints);
    } catch (const std::exception& e) {
        throw WriteException("批量写入失败: " + std::string(e.what()));
    }
}

std::future<void> KWDBClient::writeBatchAsync(const std::vector<DataPoint>& dataPoints) {
    return std::async(std::launch::async, [this, dataPoints]() {
        writeBatch(dataPoints);
    });
}

std::future<void> KWDBClient::writeStreamAsync(const std::vector<DataPoint>& dataPoints) {
    return std::async(std::launch::async, [this, dataPoints]() {
        try {
            grpcClient_->writeStream(dataPoints);
        } catch (const std::exception& e) {
            throw WriteException("流式写入失败: " + std::string(e.what()));
        }
    });
}

QueryResult KWDBClient::query(const std::string& sql) {
    if (!connected_) {
        throw QueryException("客户端未连接");
    }
    
    try {
        return grpcClient_->query(sql);
    } catch (const std::exception& e) {
        throw QueryException("查询异常: " + std::string(e.what()));
    }
}

std::future<QueryResult> KWDBClient::queryAsync(const std::string& sql) {
    return std::async(std::launch::async, [this, sql]() {
        return query(sql);
    });
}

std::future<QueryResult> KWDBClient::queryStreamAsync(const std::string& sql) {
    return std::async(std::launch::async, [this, sql]() {
        try {
            return grpcClient_->queryStream(sql);
        } catch (const std::exception& e) {
            throw QueryException("流式查询异常: " + std::string(e.what()));
        }
    });
}

QueryBuilder KWDBClient::queryBuilder() {
    return QueryBuilder(*this);
}

DataPoint KWDBClient::parseLineProtocol(const std::string& lineProtocol) {
    try {
        return parser_->parse(lineProtocol);
    } catch (const std::exception& e) {
        throw ParseException("Line Protocol解析失败: " + std::string(e.what()));
    }
}

std::string KWDBClient::toLineProtocol(const DataPoint& dataPoint) {
    return parser_->toLineProtocol(dataPoint);
}

bool KWDBClient::isConnected() const {
    return connected_;
}

const ClientConfig& KWDBClient::getConfig() const {
    return config_;
}

BatchWriter& KWDBClient::getBatchWriter() {
    return *batchWriter_;
}

bool KWDBClient::healthCheck() {
    try {
        return grpcClient_->healthCheck();
    } catch (const std::exception& e) {
        return false;
    }
}

void KWDBClient::initializeThreadPool() {
    threadPool_.clear();
    for (int i = 0; i < config_.getThreadPoolSize(); ++i) {
        threadPool_.emplace_back([this]() {
            while (!shutdown_) {
                // 线程池工作逻辑
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        });
    }
}

void KWDBClient::shutdownThreadPool() {
    shutdown_ = true;
    for (auto& thread : threadPool_) {
        if (thread.joinable()) {
            thread.join();
        }
    }
    threadPool_.clear();
}

} // namespace kwdb
